if dom < 0:
raise VmError('restore failed')
vmconfig = sxp.from_string(d['vmconfig'])
+ if not vmconfig:
+ raise VmError('bad vmconfig s-expression')
+ vmconfig = vmconfig[0]
vm.config = sxp.child_value(vmconfig, 'config')
deferred = vm.dom_configure(dom)
def vifs_cb(val, vm):
self.config = config
try:
self.name = sxp.child_value(config, 'name')
- self.memory = int(sxp.child_value(config, 'memory', '128'))
- if sxp.child(config, 'autorestart', None):
+ self.memory = int(sxp.child_value(config, 'memory') or '128')
+ if sxp.child(config, 'autorestart'):
self.autorestart = 1
self.configure_backends()
image = sxp.child_value(config, 'image')
"""
devices = []
for d in sxp.children(self.config, 'device'):
- dev = sxp.child0(d)
+ dev = sxp.child(d)
if dev is None: continue
if name == sxp.name(dev):
devices.append(dev)
if self.recreate: return
memory = self.memory
name = self.name
- cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
+ cpu = int(sxp.child_value(self.config, 'cpu') or '-1')
print 'init_domain>', memory, name, cpu
dom = xc.domain_create(mem_kb= memory * 1024, name= name, cpu= cpu)
if dom <= 0:
devices = sxp.children(self.config, 'device')
index = {}
for d in devices:
- dev = sxp.child0(d)
+ dev = sxp.child(d)
if dev is None:
raise VmError('invalid device')
dev_name = sxp.name(dev)
"""Set configuration flags if the vm is a backend for netif of blkif.
"""
for c in sxp.children(self.config, 'backend'):
- name = sxp.name(sxp.child0(c))
+ name = sxp.name(sxp.child(c))
if name == 'blkif':
self.blkif_backend = 1
elif name == 'netif':
"""
kernel = sxp.child_value(image, "kernel")
cmdline = ""
- ip = sxp.child_value(image, "ip", "dhcp")
+ ip = sxp.child_value(image, "ip") or "dhcp"
if ip:
cmdline += " ip=" + ip
root = sxp.child_value(image, "root")
args = sxp.child_value(image, "args")
if args:
cmdline += " " + args
- ramdisk = sxp.child_value(image, "ramdisk", '')
+ ramdisk = sxp.child_value(image, "ramdisk") or ''
vifs = vm.config_devices("vif")
vm.create_domain("linux", kernel, ramdisk, cmdline, len(vifs))
return vm
#todo: Same as for linux. Is that right? If so can unify them.
kernel = sxp.child_value(image, "kernel")
cmdline = ""
- ip = sxp.child_value(image, "ip", "dhcp")
+ ip = sxp.child_value(image, "ip") or "dhcp"
if ip:
cmdline += "ip=" + ip
root = sxp.child_value(image, "root")
defer = make_vif(vm.dom, vif, vmac, vm.recreate)
def fn(id):
dev = xend.netif_dev(vm.dom, vif)
- devid = sxp.attribute(val, 'id')
+ devid = sxp.child_value(val, 'id')
if devid:
dev.setprop('id', devid)
bridge = sxp.child_value(val, "bridge")
dev = sxp.child_value(val, 'dev')
if not dev:
raise VmError('vbd: Missing dev')
- mode = sxp.child_value(val, 'mode', 'r')
+ mode = sxp.child_value(val, 'mode') or 'r'
defer = make_disk(vm.dom, uname, dev, mode, vm.recreate)
def fn(vbd):
dev = xend.blkif_dev(vm.dom, vdev)
if id is None:
raise VmError('vnet: missing vif id')
dev = vm.get_device_by_id('vif', id)
- #vnet = sxp.child_value(v, 'vnet', 1)
+ #vnet = sxp.child_value(v, 'vnet') or '1'
#mac = sxp.child_value(dev, 'mac')
#vif = sxp.child_value(dev, 'vif')
#vnet_bridge(vnet, mac, vm.dom, 0)
__all__ = [
"mime_type",
"ParseError",
- "Parser",
- "atomp",
- "show",
- "show_xml",
- "elementp",
+ "Parser",
+ "show",
"name",
- "attributes",
- "attribute",
"children",
"child",
- "child_at",
- "child0",
- "child1",
- "child2",
- "child3",
- "child4",
"child_value",
- "has_id",
- "with_id",
- "child_with_id",
- "elements",
"to_string",
"from_string",
- "all_from_string",
"parse",
]
mime_type = "application/sxp"
-escapes = {
- 'a': '\a',
- 'b': '\b',
- 't': '\t',
- 'n': '\n',
- 'v': '\v',
- 'f': '\f',
- 'r': '\r',
- '\\': '\\',
- '\'': '\'',
- '\"': '\"'}
-
-k_list_open = "("
-k_list_close = ")"
-k_attr_open = "@"
-k_eval = "!"
-
-escapes_rev = {}
-for k in escapes:
- escapes_rev[escapes[k]] = k
-
class ParseError(StandardError):
def __init__(self, parser, value):
self.parent = parent
self.buf = ''
self.val = []
- self.delim = None
self.fn = fn
def push(self, fn):
class Parser:
def __init__(self):
- self.error = sys.stderr
self.reset()
def reset(self):
- self.val = []
self.eof = 0
- self.err = 0
self.line_no = 0
self.char_no = 0
- self.state = None
+ self.state = self.start_state = ParserState(self.state_start)
def push_state(self, fn):
self.state = self.state.push(fn)
def pop_state(self):
- val = self.state
self.state = self.state.parent
- if self.state and self.state.fn == self.state_start:
- # Return to start state - produce the value.
- self.val += self.state.val
- self.state.val = []
- return val
def in_class(self, c, s):
return s.find(c) >= 0
def in_printable_class(self, c):
return self.in_class(c, string.printable)
- def set_error_stream(self, error):
- self.error = error
-
- def has_error(self):
- return self.err > 0
-
def at_eof(self):
return self.eof
self.char_no += 1
if self.state is None:
- self.begin_start(None)
+ self.state = ParserState(self.state_start)
+
self.state.fn(c)
def ready(self):
- return len(self.val) > 0
+ return len(self.start_state.val) > 0
def get_val(self):
- v = self.val[0]
- self.val = self.val[1:]
+ v = self.start_state.val[0]
+ self.start_state.val = self.start_state.val[1:]
return v
def get_all(self):
- return self.val
-
- def begin_start(self, c):
- self.state = ParserState(self.state_start)
+ return self.start_state.val
- def end_start(self):
- self.val += self.state.val
- self.pop_state()
-
def state_start(self, c):
- if self.at_eof():
- self.end_start()
- elif self.in_space_class(c):
+ if self.at_eof() or self.in_space_class(c):
pass
elif self.in_comment_class(c):
- self.begin_comment(c)
- elif c == k_list_open:
- self.begin_list(c)
- elif c == k_list_close:
+ self.push_state(self.state_comment)
+ elif c == '(':
+ self.push_state(self.state_list)
+ elif c == ')':
raise ParseError(self, "syntax error: "+c)
elif self.in_string_quote_class(c):
- self.begin_string(c)
+ self.push_state(self.state_string)
+ self.state.buf = c
elif self.in_printable_class(c):
- self.begin_atom(c)
+ self.push_state(self.state_atom)
+ self.state.buf = c
elif c == chr(4):
# ctrl-D, EOT: end-of-text.
self.input_eof()
else:
raise ParseError(self, "invalid character: code %d" % ord(c))
- def begin_comment(self, c):
- self.push_state(self.state_comment)
- self.state.buf += c
-
- def end_comment(self):
- self.pop_state()
-
def state_comment(self, c):
if c == '\n' or self.at_eof():
- self.end_comment()
- else:
- self.state.buf += c
-
- def begin_string(self, c):
- self.push_state(self.state_string)
- self.state.delim = c
+ self.pop_state()
- def end_string(self):
- val = self.state.buf
- self.state.parent.val.append(val)
- self.pop_state()
-
def state_string(self, c):
if self.at_eof():
raise ParseError(self, "unexpected EOF")
- elif c == self.state.delim:
- self.end_string()
- elif c == '\\':
- self.push_state(self.state_escape)
- else:
- self.state.buf += c
-
- def state_escape(self, c):
- if self.at_eof():
- raise ParseError(self, "unexpected EOF")
- d = escapes.get(c)
- if d:
- self.state.parent.buf += d
- self.pop_state()
- elif c == 'x':
- self.state.fn = self.state_hex
- self.state.val = 0
- else:
- self.state.fn = self.state_octal
- self.state.val = 0
- self.input_char(c)
-
- def state_octal(self, c):
- def octaldigit(c):
- self.state.val *= 8
- self.state.val += ord(c) - ord('0')
- self.state.buf += c
- if self.state.val < 0 or self.state.val > 0xff:
- raise ParseError(self, "invalid octal escape: out of range " + self.state.buf)
- if len(self.state.buf) == 3:
- octaldone()
-
- def octaldone():
- d = chr(self.state.val)
- self.state.parent.buf += d
- self.pop_state()
-
- if self.at_eof():
- raise ParseError(self, "unexpected EOF")
- elif '0' <= c <= '7':
- octaldigit(c)
- elif len(self.buf):
- octaldone()
- self.input_char(c)
-
- def state_hex(self, c):
- def hexdone():
- d = chr(self.state.val)
- self.state.parent.buf += d
+ self.state.buf += c
+ # Look out for non-escaped end delimiter
+ if self.state.buf[0] == c and self.state.buf[-2] != '\\':
+ try: # parse escape sequences but fall back to something simple
+ val = eval(compile(self.state.buf,'','eval'))
+ except:
+ val = self.state.buf[1:-1] # just strip the delimiters
+ self.state.parent.val.append(val)
self.pop_state()
-
- def hexdigit(c, d):
- self.state.val *= 16
- self.state.val += ord(c) - ord(d)
- self.state.buf += c
- if self.state.val < 0 or self.state.val > 0xff:
- raise ParseError(self, "invalid hex escape: out of range " + self.state.buf)
- if len(self.state.buf) == 2:
- hexdone()
-
- if self.at_eof():
- raise ParseError(self, "unexpected EOF")
- elif '0' <= c <= '9':
- hexdigit(c, '0')
- elif 'A' <= c <= 'F':
- hexdigit(c, 'A')
- elif 'a' <= c <= 'f':
- hexdigit(c, 'a')
- elif len(buf):
- hexdone()
- self.input_char(c)
-
- def begin_atom(self, c):
- self.push_state(self.state_atom)
- self.state.buf = c
-
- def end_atom(self):
- val = self.state.buf
- self.state.parent.val.append(val)
- self.pop_state()
def state_atom(self, c):
- if self.at_eof():
- self.end_atom()
- elif (self.is_separator(c) or
- self.in_space_class(c) or
- self.in_comment_class(c)):
- self.end_atom()
- self.input_char(c)
+ if (self.at_eof() or
+ self.is_separator(c) or
+ self.in_space_class(c) or
+ self.in_comment_class(c)):
+ val = self.state.buf
+ self.state.parent.val.append(val)
+ self.pop_state()
+ if not self.at_eof():
+ self.input_char(c)
else:
self.state.buf += c
- def begin_list(self, c):
- self.push_state(self.state_list)
-
- def end_list(self):
- val = self.state.val
- self.state.parent.val.append(val)
- self.pop_state()
-
def state_list(self, c):
if self.at_eof():
raise ParseError(self, "unexpected EOF")
- elif c == k_list_close:
- self.end_list()
+ elif c == ')':
+ val = self.state.val
+ self.state.parent.val.append(val)
+ self.pop_state()
else:
self.state_start(c)
-def atomp(sxpr):
- """Check if an sxpr is an atom.
- """
- if sxpr.isalnum() or sxpr == '@':
- return 1
- for c in sxpr:
- if c in string.whitespace: return 0
- if c in '"\'\\(){}[]<>$#&%^': return 0
- if c in string.ascii_letters: continue
- if c in string.digits: continue
- if c in '.-_:/~': continue
- return 0
- return 1
-
def show(sxpr, out=sys.stdout):
"""Print an sxpr in bracketed (lisp-style) syntax.
"""
if isinstance(sxpr, types.ListType):
- out.write(k_list_open)
- i = 0
+ out.write('(')
for x in sxpr:
- if i: out.write(' ')
show(x, out)
- i += 1
- out.write(k_list_close)
- elif isinstance(sxpr, types.StringType) and atomp(sxpr):
- out.write(sxpr)
+ out.write(' ')
+ out.write(')')
else:
- #out.write("'" + str(sxpr) + "'")
out.write(repr(str(sxpr)))
-def show_xml(sxpr, out=sys.stdout):
- """Print an sxpr in XML syntax.
- """
- if isinstance(sxpr, types.ListType):
- element = name(sxpr)
- out.write('<%s' % element)
- for attr in attributes(sxpr):
- out.write(' %s=%s' % (attr[0], attr[1]))
- out.write('>')
- i = 0
- for x in children(sxpr):
- if i: out.write(' ')
- show_xml(x, out)
- i += 1
- out.write('</%s>' % element)
- elif isinstance(sxpr, types.StringType) and atomp(sxpr):
- out.write(sxpr)
- else:
- out.write(str(sxpr))
-
-def elementp(sxpr, elt=None):
- """Check if an sxpr is an element of the given type.
-
- sxpr sxpr
- elt element type
- """
- return (isinstance(sxpr, types.ListType)
- and len(sxpr)
- and (None == elt or sxpr[0] == elt))
-
def name(sxpr):
- """Get the element name of an sxpr.
- If the sxpr is not an element (i.e. it's an atomic value) its name
- is None.
-
- sxpr
-
- returns name (None if not an element).
+ """Get the element name of an sxpr, or None if a bad sxpr.
"""
- val = None
if isinstance(sxpr, types.StringType):
- val = sxpr
- elif isinstance(sxpr, types.ListType) and len(sxpr):
- val = sxpr[0]
- return val
-
-def attributes(sxpr):
- """Get the attribute list of an sxpr.
-
- sxpr
-
- returns attribute list
- """
- val = []
- if isinstance(sxpr, types.ListType) and len(sxpr) > 1:
- attr = sxpr[1]
- if elementp(attr, k_attr_open):
- val = attr[1:]
- return val
-
-def attribute(sxpr, key, val=None):
- """Get an attribute of an sxpr.
-
- sxpr sxpr
- key attribute key
- val default value (default None)
-
- returns attribute value
- """
- for x in attributes(sxpr):
- if x[0] == key:
- val = x[1]
- break
- return val
+ return sxpr
+ if isinstance(sxpr, types.ListType) and len(sxpr):
+ return sxpr[0]
+ return None
def children(sxpr, elt=None):
- """Get children of an sxpr.
-
- sxpr sxpr
- elt optional element type to filter by
-
- returns children (filtered by elt if specified)
+ """Get children of an s-expression @sxpr, optionally filtered by
+ element type @elt.
"""
- val = []
- if isinstance(sxpr, types.ListType) and len(sxpr) > 1:
- i = 1
- x = sxpr[i]
- if elementp(x, k_attr_open):
- i += 1
- val = sxpr[i : ]
+ if not isinstance(sxpr, types.ListType): return []
+ val = filter(lambda x: isinstance(x, types.ListType) and len(x) > 0, sxpr)
if elt:
- def iselt(x):
- return elementp(x, elt)
- val = filter(iselt, val)
- return val
-
-def child(sxpr, elt, val=None):
- """Get the first child of the given element type.
-
- sxpr sxpr
- elt element type
- val default value
- """
- for x in children(sxpr):
- if elementp(x, elt):
- val = x
- break
- return val
-
-def child_at(sxpr, index, val=None):
- """Get the child at the given index (zero-based).
-
- sxpr sxpr
- index index
- val default value
- """
- kids = children(sxpr)
- if len(kids) > index:
- val = kids[index]
- return val
-
-def child0(sxpr, val=None):
- """Get the zeroth child.
- """
- return child_at(sxpr, 0, val)
-
-def child1(sxpr, val=None):
- """Get the first child.
- """
- return child_at(sxpr, 1, val)
-
-def child2(sxpr, val=None):
- """Get the second child.
- """
- return child_at(sxpr, 2, val)
-
-def child3(sxpr, val=None):
- """Get the third child.
- """
- return child_at(sxpr, 3, val)
-
-def child4(sxpr, val=None):
- """Get the fourth child.
- """
- return child_at(sxpr, 4, val)
-
-def child_value(sxpr, elt, val=None):
- """Get the value of the first child of the given element type.
- Assumes the child has an atomic value.
-
- sxpr sxpr
- elt element type
- val default value
- """
- kid = child(sxpr, elt)
- if kid:
- val = child_at(kid, 0, val)
+ val = filter(lambda x,y=elt: x[0] == y, val)
return val
-def has_id(sxpr, id):
- """Test if an s-expression has a given id.
+def child(sxpr, elt=None, idx=0):
+ """Get the @idx'th child of the optional filtering type @elt in @sxpr.
"""
- return attribute(sxpr, 'id') == id
-
-def with_id(sxpr, id, val=None):
- """Find the first s-expression with a given id, at any depth.
-
- sxpr s-exp or list
- id id
- val value if not found (default None)
+ x = children(sxpr, elt)
+ if len(x) > idx:
+ return x[idx]
+ return None
- return s-exp or val
+def child_value(sxpr, elt=None):
+ """Get the value of the first child of @sxpr with the optional type @elt.
"""
- if isinstance(sxpr, types.ListType):
- for n in sxpr:
- if has_id(n, id):
- val = n
- break
- v = with_id(n, id)
- if v is None: continue
- val = v
- break
- return val
-
-def child_with_id(sxpr, id, val=None):
- """Find the first child with a given id.
-
- sxpr s-exp or list
- id id
- val value if not found (default None)
-
- return s-exp or val
- """
- if isinstance(sxpr, types.ListType):
- for n in sxpr:
- if has_id(n, id):
- val = n
- break
- return val
-
-def elements(sxpr, ctxt=None):
- """Generate elements (at any depth).
- Visit elements in pre-order.
- Values generated are (node, context)
- The context is None if there is no parent, otherwise
- (index, parent, context) where index is the node's index w.r.t its parent,
- and context is the parent's context.
-
- sxpr s-exp
-
- returns generator
- """
- yield (sxpr, ctxt)
- i = 0
- for n in children(sxpr):
- if isinstance(n, types.ListType):
- # Calling elements() recursively does not generate recursively,
- # it just returns a generator object. So we must iterate over it.
- for v in elements(n, (i, sxpr, ctxt)):
- yield v
- i += 1
+ x = child(sxpr, elt)
+ if not isinstance(x, types.ListType) or len(x) < 2:
+ return None
+ return x[1]
def to_string(sxpr):
- """Convert an sxpr to a string.
-
- sxpr sxpr
- returns string
+ """Convert an s-expression @sxpr to a string.
"""
io = StringIO()
show(sxpr, io)
return val
def from_string(str):
- """Create an sxpr by parsing a string.
-
- str string
- returns sxpr
- """
- io = StringIO(str)
- vals = parse(io)
- if vals is []:
- return None
- else:
- return vals[0]
-
-
-def all_from_string(str):
- """Create an sxpr list by parsing a string.
-
- str string
- returns sxpr list
+ """Create an sxpr list from a given input string @str.
"""
io = StringIO(str)
vals = parse(io)
return vals
def parse(io):
- """Completely parse all input from 'io'.
-
- io input file object
- returns list of values, None if incomplete
- raises ParseError on parse error
+ """Completely parse all input from file @io.
"""
pin = Parser()
while 1:
else:
val = None
return val
-
+
if __name__ == '__main__':
- print ">main"
pin = Parser()
- while 1:
- buf = sys.stdin.read(1024)
- #buf = sys.stdin.readline()
- pin.input(buf)
- while pin.ready():
- val = pin.get_val()
- print
- print '****** val=', val
- if len(buf) == 0:
- break
-
+ buf = sys.stdin.read(1024)
+ pin.input(buf)
+ while pin.ready():
+ print '\n****** val=', pin.get_val()